package com.ccp.dev.system.service;

import com.ccp.dev.core.basic.base.BaseService;
import com.ccp.dev.core.basic.consts.SystemConst;
import com.ccp.dev.core.basic.model.SysAuditModelType;
import com.ccp.dev.core.basic.util.ContextUtil;
import com.ccp.dev.core.basic.util.UUIDUtils;
import com.ccp.dev.core.util.*;
import com.ccp.dev.system.dao.ResourcesDao;
import com.ccp.dev.system.dao.ResourcesUrlDao;
import com.ccp.dev.system.dao.SysOrgDao;
import com.ccp.dev.system.dao.SysTenantResourceDao;
import com.ccp.dev.system.model.*;
import com.ccp.dev.system.model.menuauto.ClassInfoModel;
import com.ccp.dev.system.model.menuauto.MethodInfoModel;
import com.ccp.dev.system.model.util.GetAllMenuPath;
import com.ccp.dev.system.util.XmlUtil;
import org.apache.commons.lang.StringUtils;
import org.dom4j.Document;
import org.dom4j.Element;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.xml.bind.JAXBException;
import java.io.InputStream;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 资源管理service
 *
 * @author nd
 */
@Service
public class ResourcesService extends BaseService<Resources> {
    /**
     * 菜单自动生成成功标识
     */
    private static final String MENU_AUTO_SUCCESS = "SUCCESS";

    private static final String IS_DISPLAY_IN_MENU = "1";
    /**
     * 默认的用户ID，对应sys_res表的CREATOR字段，可以用来统一的修改、删除数据
     */
    private static final String DEFAULT_CREATOR = "999999999L";
    /**
     * 操作类型，只进行新增操作
     */
    private static final String IMPORT_INSERT_ONLY = "1";
    /**
     * 操作类型，根据resId进行判断，如果存在则进行更新
     */
    public static final String IMPORT_INSERT_UPDATE = "2";

    private static final String LIST_URL = "list";

    @Resource
    private ResourcesDao resourcesDao;

    @Resource
    private SysOrgDao sysOrgDao;

    @Resource
    private ResourcesUrlDao resourcesUrlDao;

    @Resource
    private SysTenantResourceDao sysTenantResourceDao;

    @Resource
    private SysTenantDynamicDataService sysTenantDynamicDataService;

    @Resource
    private SysRoleService sysRoleService;

    @Resource
    private SysTenantResourceService sysTenantResourceService;

    @Resource
    private SubSystemService subSystemService;

    @Resource
    private SysOrgService sysOrgService;

    @Value("${threeNumber.res}")
    private Boolean threeNumberRes = false;


    /**
     * 保存资源
     *
     * @param resources 资源对象
     * @param aryName   子url名称
     * @param aryUrl    子url
     */
    @Transactional(rollbackFor = Exception.class)
    public void saveResources(Resources resources, String[] aryName, String[] aryUrl, String tenantId, String systemId) {
        String resId;
        String parentId = resources.getParentId();
        Resources parentRes = resourcesDao.getById(parentId);
        Short isPublic = parentRes.getIsPublic();
        if (SystemConst.PUBLIC_TOP_RESOURCE_ID.equals(parentId)) {
            isPublic = SystemConst.PUBLIC_N;
        }
        resources.setIsPublic(isPublic);
        String path = "";
        String currentIconSkin = resources.getIconSkin();
        if(StringUtil.isEmpty(currentIconSkin)){
            currentIconSkin = Resources.DEFAULT_ICON;
        }
        String iconSkin = "";
        if(currentIconSkin.indexOf("layui-icon") != -1){
            iconSkin = StringPool.SPACE + SystemConst.ZTREE_ICON + StringPool.SPACE + "layui-icon" + StringPool.SPACE + currentIconSkin + StringPool.SPACE;
        }else{
            iconSkin = StringPool.SPACE + SystemConst.ZTREE_ICON + StringPool.SPACE + SystemConst.ICON_FONT + StringPool.SPACE + currentIconSkin + StringPool.SPACE;
        }

        resources.setIconSkin(iconSkin);

        if (resources.getResId() == null) {
            resId = UUIDUtils.getUUIDFor32();
            resources.setResId(resId);

            if (BeanUtils.isNotEmpty(parentRes)) {
                if (StringUtil.isNotEmpty(parentRes.getPath())) {
                    path = parentRes.getPath() + StringPool.COLON + resId;
                }
            } else {
                path = resId;
            }
            resources.setPath(path);
            resources.setResId(resId);
            resources.setSystemId(systemId);

            SysOrg sysOrg = sysOrgService.getOrgByTenId(tenantId);

            resourcesDao.add(resources);
            SysTenantResource sysTenantResource = new SysTenantResource();
            sysTenantResource.setTenantId(tenantId);
            sysTenantResource.setTenantResourceId(UUIDUtils.getUUIDFor32());
            sysTenantResource.setResourceId(resources.getResId());
            sysTenantResource.setSystemId(systemId);
            sysTenantResourceDao.add(sysTenantResource);
        } else {
            resId = resources.getResId();
            if (BeanUtils.isNotEmpty(parentRes)) {
                if (StringUtil.isNotEmpty(parentRes.getPath())) {
                    path = parentRes.getPath() + StringPool.COLON + resId;
                }
            } else {
                path = resId;
            }
            resources.setPath(path);
            resourcesDao.update(resources);
            /*
             *删除资源的子url
             */
            resourcesUrlDao.delByResId(resId);
        }
        /*
         *修改子url
         */
        if (BeanUtils.isEmpty(aryName)) {
            return;
        }
        for (int i = 0; i < aryName.length; i++) {
            String url = aryUrl[i];
            if (StringUtil.isEmpty(url)) {
                continue;
            }
            ResourcesUrl resourceUrl = new ResourcesUrl();
            resourceUrl.setResId(resId);
            resourceUrl.setResUrlId(UUIDUtils.getUUIDFor32());
            resourceUrl.setName(aryName[i]);
            resourceUrl.setUrl(url);
            resourcesUrlDao.add(resourceUrl);
        }
    }

    /**
     * 删除资源
     *
     * @param lAryId 要删除资源的id数组
     */
    @Transactional(rollbackFor = Exception.class)
    public String delResourcesByIds(String[] lAryId) {
        String msg = "delete.success";
        for (String id : lAryId) {
            if (SystemConst.PUBLIC_RESOURCE_ROOT_ID.equals(id)) {
                msg = "delete.resource.failure.public.not.allowed";
                continue;
            }
            resourcesUrlDao.delByResId(id);
            resourcesDao.delById(id);
        }
        return msg;
    }

    /**
     * 获取所有的公共资源
     *
     * @param map 参数
     * @return list
     */
    public List<Resources> queryAllPublicRes(Map map) {
        return this.resourcesDao.queryAllPublicRes(map);
    }

    /**
     * 查询组织树节点列表
     * @param orgId 所选组织id
     * @param type  资源类型，0:非公用资源；1:公用资源；2;所有资源
     * @param systemId 子系统id
     * @return list
     */
    public List<Resources> queryResTreeData(String orgId,int type,String systemId) {
        List<Resources> topTenantRes = null;
        SysOrg currOrg = sysOrgService.getOneById(orgId);
        //上级组织的id
        String orgSupId = currOrg.getOrgSupId();
        if(SystemConst.TOP_ORG_ID.equals(orgSupId)){
            Map map = new HashMap(2);
            map.put("systemId", systemId);
            if (type == 0) {
                map.put("isPublic", 0);
            } else if (type == 1) {
                map.put("isPublic", 1);
            } else {
                map.put("isPublic", null);
            }
            topTenantRes = resourcesDao.getBySystemId(map);
        }else{
            String tenantId = sysOrgService.getTenantIdByOrgId(orgSupId);
            topTenantRes = queryBySystemIdAndTenId(systemId,tenantId,type);
        }
        if (type == 0){
            Resources notPublicResTop = resourcesDao.getById(SystemConst.DEFAULT_TOP_SOURCE_ID);
            notPublicResTop.setChecked(Resources.IS_CHECKED_Y);
            topTenantRes.add(notPublicResTop);
        }
        //被分配资源的租户id
        String tenantId = sysOrgService.getTenantIdByOrgId(orgId);
        List<Resources> tenantContainRes = queryBySystemIdAndTenId(systemId,tenantId,type);
        for (Resources res : tenantContainRes) {
            for(Resources topRes : topTenantRes){
                if (topRes.getResId().equals(res.getResId())) {
                    topRes.setChecked(Resources.IS_CHECKED_Y);
                }
            }
        }
        return topTenantRes;
    }

    /**
     * 根据角色id 查询用户能访问的菜单资源
     *
     * @param roleId 角色id
     * @return
     */
    public List<Resources> queryUserMenuResourcesByRoleId(String roleId) {
        /*
        查找用户所属角色能访问的菜单资源
        从顶级菜单向下级查找所有资源信息
         */

        return null;
    }

    /**
     * 根据id查资源
     *
     * @param resId 资源id
     * @return 资源实体对象
     */
    public Resources getById(String resId) {
        return resourcesDao.getById(resId);
    }

    /**
     * 导出资源信息xml文件
     *
     * @param resId    资源id
     * @param tenantId 租户id
     * @return xml字符串
     */
    public String exportXml(String resId, String tenantId) throws JAXBException {
        Map<String, String> map = new HashMap<String, String>(2);
        map.put("resId", resId);
        map.put("tenantId", tenantId);
        Resources resources = resourcesDao.getByIdAndTent(map);
        ResourcesXmlList resXmlList = new ResourcesXmlList();
        ResourcesXml resourcesXml = new ResourcesXml();
        if (BeanUtils.isNotEmpty(resources)) {
            List<ResourcesXml> resList = new ArrayList<ResourcesXml>();
            resourcesXml = getResourcesXml(resourcesXml, resources, tenantId);
            resList.add(resourcesXml);
            resXmlList.setResourcesXmlList(resList);
        }
        return XmlBeanUtil.marshall(resXmlList, ResourcesXmlList.class);
    }

    /**
     * 递归查找子资源(为导出资源)
     *
     * @param resXml
     * @param res
     * @return
     */
    private ResourcesXml getResourcesXml(ResourcesXml resXml, Resources res, String tenantId) {
        resXml.setResour(res);
        List<Resources> resList = getByParentIdAndTent(res.getResId(), tenantId);
        if (BeanUtils.isNotEmpty(resList)) {
            List<ResourcesXml> resourcesXmls = resXml.getResourcesList();
            for (Resources resource : resList) {
                ResourcesXml resourcesXml = new ResourcesXml();
                resourcesXml = getResourcesXml(resourcesXml, resource, tenantId);
                resourcesXmls.add(resourcesXml);
            }
            resXml.setResourcesList(resourcesXmls);
        }
        return resXml;
    }

    public List<Resources> getByParentIdAndTent(String id, String tenantId) {
        Map<String, String> map = new HashMap<String, String>(2);
        map.put("resId", id);
        map.put("tenantId", tenantId);
        return resourcesDao.queryByParentIdAndTent(map);
    }

    /**
     * 导入资源xml文件
     *
     * @param inputStream 输入流
     * @param systemId    系统id
     */
    @Transactional(rollbackFor = Exception.class)
    public void importXml(InputStream inputStream, String systemId,String selectTenantId) throws Exception {
        String xml = FileUtil.inputStream2String(inputStream);
        Document doc = Dom4jUtil.loadXml(xml);
        Element root = doc.getRootElement();
        XmlUtil.checkXmlFormat(root, "res", "resources");
        ResourcesXmlList resXmlList = (ResourcesXmlList) XmlBeanUtil.unmarshall(xml, ResourcesXmlList.class);
        addResource(resXmlList.getResourcesXmlList().get(0),systemId,selectTenantId);
    }

    /**
     * 解析xml递归插入资源
     *
     * 修改导入资源：根据xml文件中的resId进行导入，若数据库中存在当前xml中的resId则更新，不存在则新增
     *
     * @param resXml
     * @param systemId
     */
    @Transactional(rollbackFor = Exception.class)
    public void addResource(ResourcesXml resXml, String systemId,String selectTenantId) throws Exception {
        Resources res = resXml.getResour();
        String resId = res.getResId();
        if(StringUtils.isEmpty(resId)){
            throw new Exception();
        }else{
            Resources resources = this.resourcesDao.getById(resId);
            if(BeanUtils.isEmpty(resources)){
                SysTenantResource tenantResource = new SysTenantResource();
                this.add(res);
                tenantResource.setResourceId(res.getResId());
                tenantResource.setStatus(1);
                tenantResource.setSystemId(systemId);
                String tenantId = res.getTenantId();
                tenantResource.setTenantId(selectTenantId);
                tenantResource.setTenantResourceId(UUIDUtils.getUUIDFor32());
                sysTenantResourceDao.add(tenantResource);
                List<ResourcesXml> resXmlList = resXml.getResourcesList();
                for (ResourcesXml resourcesXml : resXmlList) {
                    addResource(resourcesXml, systemId,selectTenantId);
                }
            }else{
                this.update(res);
                List<ResourcesXml> resXmlList = resXml.getResourcesList();
                for (ResourcesXml resourcesXml : resXmlList) {
                    addResource(resourcesXml, systemId,selectTenantId);
                }
            }
        }
    }

    /**
     * @param lAryId 按顺序排列的同级节点的id数组
     */
    @Transactional(rollbackFor = Exception.class)
    public void updateSn(String[] lAryId) {
        if (BeanUtils.isNotEmpty(lAryId)) {
            Map<String, Object> param = new HashMap<String, Object>(2);
            int sn = 1;
            for (int i = 0; i < lAryId.length; i++) {
                String resId = lAryId[i];
                param.put("resId", resId);
                param.put("sn", sn++);
                resourcesDao.updateSn(param);
            }
        }
    }

    /**
     * 移动节点 将某节点移动到另一个节点下 成为另一个节点的子节点
     *
     * @param sourceId 要移动的节点id
     * @param targetId 目标节点id
     */
    @Transactional(rollbackFor = Exception.class)
    public void moveResources(String sourceId, String targetId) throws Exception{
        if(sourceId.equals(targetId)){
            throw  new Exception("resources.move.notTheSame");
        }
        //要移动的节点
        Resources source = resourcesDao.getById(sourceId);
        Resources target = resourcesDao.getById(targetId);
        //移动节点之前的path 用于查询子节点
        String oldPath = source.getPath();
        //查询所有的子节点
        Map<String, String> params = new HashMap<>(1);
        params.put("path", oldPath + ":%");
        List<Resources> resourcesList = resourcesDao.getResByPath(params);
        List<Resources> isChild = resourcesList.stream().filter( a -> a.getResId().equals(targetId)).collect(Collectors.toList());
        if(!isChild.isEmpty()){
            throw  new Exception("resources.move.notMoveToChild");
        }
        //接收节点的path
        String targetPath = target.getPath();

        //将拖动的节点父节点设置为目标节点的ID
        source.setParentId(target.getResId());
        String currentPath = targetPath + ":" + sourceId;
        //设置资源移动后的路径
        source.setPath(currentPath);
        resourcesDao.update(source);

        List<Resources> rtnList = new ArrayList<>();
        if (!resourcesList.isEmpty()) {
            initChild(source.getResId(), source.getPath(), rtnList, resourcesList);
            for (Iterator<Resources> it = rtnList.iterator(); it.hasNext(); ) {
                Resources res = it.next();
                resourcesDao.update(res);
            }
        }
    }

    @Transactional(rollbackFor = Exception.class)
    public void initChild(String parentResId, String parentPath, List<Resources> rtnList, List<Resources> allResources) {
        for (Iterator<Resources> it = allResources.iterator(); it.hasNext(); ) {
            Resources res = it.next();
            if (!res.getParentId().equals(parentResId)) {
                continue;
            }
            String path = parentPath + StringPool.COLON + res.getResId();
            res.setPath(path);
            rtnList.add(res);
            initChild(res.getResId(), path, rtnList, allResources);
        }
    }

    /**
     * 验证类是否存在
     *
     * @param className 完整包名.类名
     * @return 存在返回true 不存在返回false
     */
    public boolean validClass(String className) {
        return BeanUtils.validClass(className);
    }

    /**
     * 查询全部资源URL数据
     *
     * @param classPath controller类路径
     * @return string 要生成的资源以字符串形式返回
     */
    public String queryAllMenuPath(String classPath) throws Exception {
        List<ClassInfoModel> list = GetAllMenuPath.GetAllMenuPath(classPath, null, "");
        StringBuilder sb = new StringBuilder();
        for (ClassInfoModel classInfoModel : list) {
            List<MethodInfoModel> methodInfoModelList = classInfoModel.getMethodInfoModelList();
            for (MethodInfoModel methodInfoModel : methodInfoModelList) {
                //完整的URL路径
                String compUrl = methodInfoModel.getCompleteUrl();
                //校验这个url是否已经存在于系统中，如果存在则跳过此方法的后续处理
                List<Resources> resourcesInDB = resourcesDao.queryByUrl(compUrl);
                if (resourcesInDB != null && resourcesInDB.size() > 0) {
                    continue;
                }
                sb.append(methodInfoModel.getActionDesc() + "<br>");
            }
        }
        return sb.toString();

    }

    /**
     * 菜单自动生成
     *
     * @param classPath controller类路径
     * @param parentId  选择的菜单节点
     */
    @Transactional(rollbackFor = Exception.class)
    public String menuAuto(String classPath, String parentId, String tenantId, String systemId) throws Exception {
        String resultMsg = MENU_AUTO_SUCCESS;
        //构造一个默认的菜单，属性为不显示到菜单，用于放置一些没有明确逻辑关系的菜单
        Resources defaultRes = getDefaultRes();

        //首先只处理URL为list.ht的方法
        List<ClassInfoModel> classInfoOnlyList = GetAllMenuPath.GetAllMenuPath(classPath, null, LIST_URL);
        addUrl2Db(resourcesDao, defaultRes, classInfoOnlyList, parentId, tenantId, systemId);

        //然后处理Controller类中的全部资源URL数据
        List<ClassInfoModel> allClassInfoModelList = GetAllMenuPath.GetAllMenuPath(classPath, null, "");
        addUrl2Db(resourcesDao, defaultRes, allClassInfoModelList, parentId, tenantId, systemId);
        return resultMsg;
    }

    /**
     * 构造一个默认的菜单，用于放没有明确逻辑关系的URL
     *
     * @return 默认的Resources对象
     */
    private static Resources getDefaultRes() {
        Resources defaultRes = setDefaultData();
        defaultRes.setResName("功能权限");
        defaultRes.setAlias("sys_functions");
        defaultRes.setIcon("");
        defaultRes.setParentId(SystemConst.DEFAULT_TOP_SOURCE_ID);
        defaultRes.setDefaultUrl("");
        defaultRes.setPath(defaultRes.getResId());
        return defaultRes;
    }

    /**
     * 构造resources对象的默认值
     *
     * @return resources对象
     */
    private static Resources setDefaultData() {
        Resources defaultRes = new Resources();
        defaultRes.setResId(UUIDUtils.getUUIDFor32());
        defaultRes.setCreator(DEFAULT_CREATOR);
        defaultRes.setSn(10);
        defaultRes.setIsFolder((short) 1);
        defaultRes.setIsDisplayInMenu((short) 0);
        defaultRes.setIsOpen((short) 1);
        defaultRes.setSystemId(SystemConst.DEFAULT_SYSTEM_ID);
        return defaultRes;
    }

    /**
     * 添加菜单到数据库的主方法
     *
     * @param resourcesDao       连接数据库
     * @param defaultRes         默认的菜单容器
     * @param classInfoModelList 需要处理的类及方法数据
     * @param parentId           页面选择的菜单资源id
     */
    @Transactional(rollbackFor = Exception.class)
    public void addUrl2Db(ResourcesDao resourcesDao, Resources defaultRes, List<ClassInfoModel> classInfoModelList, String parentId, String tenantId, String systemId) {
        //构造需要新增到数据库中的sys_res数据
        for (ClassInfoModel classInfoModel : classInfoModelList) {
            //类上的根路径
            String classReqVal = classInfoModel.getClassReqMapValue();
            List<MethodInfoModel> methodInfoModelList = classInfoModel.getMethodInfoModelList();
            for (MethodInfoModel methodInfoModel : methodInfoModelList) {
                //方法上的requestMapping，已经拼接了.ht
                String methodReqUrl = methodInfoModel.getMethodReqMapValue();
                //完整的URL路径
                String compUrl = methodInfoModel.getCompleteUrl();
                //校验这个url是否已经存在于系统中，如果存在则跳过此方法的后续处理
                List<Resources> resourcesInDB = resourcesDao.queryByUrl(compUrl);
                if (resourcesInDB != null && resourcesInDB.size() > 0) {
                    continue;
                }

                Resources resForAdd = new Resources();
                short inMenu = 0;
                //如果本次处理的URL为list.ht，则父菜单为页面选择的菜单资源id
                if (LIST_URL.equals(methodReqUrl)) {
                    inMenu = 1;
                    resForAdd = getNewResForAdd(parentId, inMenu, methodInfoModel, systemId);
                } else {
                    //如果本次处理的不是list.ht，则检测一下是否已经存在了list.ht的菜单，如果已经存在将添加为list的子菜单
                    List<Resources> listUrlInDB = resourcesDao.queryByUrl(classReqVal + LIST_URL);
                    if (listUrlInDB != null && listUrlInDB.size() > 0) {
                        parentId = listUrlInDB.get(0).getResId();
                    }
                    resForAdd = getNewResForAdd(parentId, inMenu, methodInfoModel, systemId);
                }
                Resources parentRes = resourcesDao.getById(parentId);
                if (BeanUtils.isNotEmpty(parentRes)) {
                    resForAdd.setPath(parentRes.getPath() + ":" + resForAdd.getResId());
                } else {
                    resForAdd.setPath(resForAdd.toString());
                }
                Map<String, Object> params = new HashMap<>(2);
                params.put("alias", resForAdd.getAlias());
                params.put("systemId", SystemConst.DEFAULT_SYSTEM_ID);
                //需要检测一下可能存在的资源别名，在原来的基础上+1
                Integer aliasCount = resourcesDao.isAliasExists(params);
                if (aliasCount > 0) {
                    resForAdd.setAlias(resForAdd.getAlias() + aliasCount);
                }
                if ("0".equals(tenantId)) {
                    resForAdd.setCreator(tenantId);
                }else{
                    SysOrg sysOrg = sysOrgService.getOrgByTenId(tenantId);
                    resForAdd.setCreator(sysOrg.getOrgName());
                }
                String iconSkin = StringPool.SPACE + SystemConst.ZTREE_ICON + StringPool.SPACE + SystemConst.ICON_FONT + StringPool.SPACE + Resources.DEFAULT_ICON + StringPool.SPACE;
                resForAdd.setIconSkin(iconSkin);
                resourcesDao.add(resForAdd);
                //入租户和资源的关系表
                SysTenantResource tenantResource = new SysTenantResource();
                tenantResource.setResourceId(resForAdd.getResId());
                tenantResource.setSystemId(resForAdd.getSystemId());
                tenantResource.setTenantId(tenantId);
                tenantResource.setStatus(1);
                tenantResource.setTenantResourceId(UUIDUtils.getUUIDFor32());
                sysTenantResourceDao.add(tenantResource);
            }
        }
    }

    /**
     * 构造需要添加到数据里的菜单数据
     *
     * @return 默认的Resources对象
     */
    private static Resources getNewResForAdd(String parentId, short inMenu, MethodInfoModel methodInfoModel, String systemId) {
        Resources resForAdd = setDefaultData();
        resForAdd.setResName(methodInfoModel.getActionDesc());
        resForAdd.setAlias(methodInfoModel.getActionDescPY());
        resForAdd.setDefaultUrl(methodInfoModel.getCompleteUrl());
        resForAdd.setParentId(parentId);
        resForAdd.setIsDisplayInMenu(inMenu);
        resForAdd.setSystemId(systemId);
        resForAdd.setIsPublic(SystemConst.PUBLIC_N);
        return resForAdd;
    }

    /**
     * 根据系统id和租户id共同筛选获取所有的资源列表
     *
     * @param systemId 系统id
     * @param supTenId 租户id
     * @param type     资源类型，0:非公用资源；1:公用资源；null;所有资源
     * @return 资源集合list
     */
    public List<Resources> queryBySystemIdAndTenId(String systemId, String supTenId, int type) {
        Map<String, Object> params = new HashMap<>(3);
        params.put("systemId", systemId);
        params.put("tenId", supTenId);
        if (type == 0) {
            params.put("isPublic", 0);
        } else if (type == 1) {
            params.put("isPublic", 1);
        } else {
            params.put("isPublic", null);
        }
        return this.resourcesDao.queryBySystemIdAndTenId(params);
    }

    /**
     * 根据角色获取租户资源树
     *
     * @param roleId 角色id
     * @param type   资源类型，0:非公用资源；1:公用资源；2;所有资源
     * @return list
     */
    public List<Resources> queryTreeByRoleId(String roleId, int type) {
        String tenantId = sysTenantDynamicDataService.getTenantIdByDataId(roleId);
        SysRole sysRole = sysRoleService.getOneById(roleId);
        String systemId = sysRole.getSystemId();
        //租户资源
        List<Resources> resourcesList = queryBySystemIdAndTenId(systemId, tenantId, type);
        if (type == 0){
            Resources notPublicResTop = resourcesDao.getById(SystemConst.DEFAULT_TOP_SOURCE_ID);
            notPublicResTop.setChecked(Resources.IS_CHECKED_Y);
            resourcesList.add(notPublicResTop);
        }
        //当前角色拥有资源
        List<SysTenantResource> tenantResourceList = sysTenantResourceService.queryByTenAndResAndRole(systemId, tenantId, roleId);
        Set<String> set = new HashSet<>();
        if (BeanUtils.isNotEmpty(tenantResourceList)) {
            for (SysTenantResource tenants : tenantResourceList) {
                set.add(tenants.getResourceId());
            }
        }
        if (BeanUtils.isNotEmpty(resourcesList)) {
            for (Resources res : resourcesList) {
                if (set.contains(res.getResId())) {
                    res.setChecked(Resources.IS_CHECKED_Y);
                } else {
                    res.setChecked(Resources.IS_CHECKED_N);
                }
            }
        }
        return resourcesList;
    }

    /**
     * 根据系统id和父节点id获取资源节点。
     * <pre>
     * 1.根据父节点id获取资源获取到即返回。
     * 2.如果获取不到则根据子系统相关数据构建资源根节点进行返回。
     * </pre>
     *
     * @param parentId
     * @return
     */
    public Resources getParentResourcesByParentId(String systemId, String parentId) {
        Resources parent = resourcesDao.getById(parentId);
        if (parent != null) {
            return parent;
        }
        SubSystem sys = subSystemService.getOneById(systemId);
        parent = new Resources();
        parent.setResId(Resources.ROOT_ID);
        parent.setParentId(Resources.ROOT_PID);
        parent.setSn(0);
        parent.setSystemId(systemId);
        parent.setAlias(sys.getAlias());
        parent.setIsDisplayInMenu(Resources.IS_DISPLAY_IN_MENU_Y);
        parent.setIsFolder(Resources.IS_FOLDER_Y);
        parent.setIsOpen(Resources.IS_OPEN_Y);
        parent.setResName(sys.getSysName());
        return parent;

    }


    /**
     * 根据系统别名列表和url获取url和角色的映射。
     *
     * @param aliasList 系统别名
     * @param url       请求url
     * @return list
     */
    @SuppressWarnings("unchecked")
    public List<ResourcesUrlExt> queryDefaultUrlAndRoleByUrlSystemAliasList(List<String> aliasList, String url) {
        Map<String, Object> params = new HashMap<String, Object>(2);
        params.put("aliasList", aliasList);
        params.put("url", url);
        return this.resourcesDao.queryDefaultUrlAndRoleByUrlSystemAliasList(params);
    }

    /**
     * 查询菜单 用户能访问的菜单
     *
     * @param systemId 子系统id
     * @param roleId 角色id
     * @return ResultData
     */
    public List<Resources> queryListMenu(String systemId, String roleId) {
        //判断是否是超管登录
        if(ContextUtil.isSuperAdmin()){
            List<Resources> retList = new ArrayList<>();
            Resources parent = resourcesDao.getByAlias(Resources.USERORG_ALIAS);
            List<Resources> child = new ArrayList<>();
            child.add(resourcesDao.getByAlias(Resources.ORG_MANAGE_ALIAS));
            parent.setList(child);
            retList.add(parent);
            return retList;
        }
        Map<String, Object> param = new HashMap<>(2);
        String currUserId = ContextUtil.getCurrentUserId();
        param.put("systemId", systemId);
        param.put("isDisplayInMenu", IS_DISPLAY_IN_MENU);
        param.put("roleId", roleId);
        param.put("userId", currUserId);
        List<Resources> retRes = new ArrayList<>();
        List<SysRole> allRole = sysRoleService.queryByUserId(currUserId);
        boolean isContainThreeRole = sysRoleService.isContainThreeRole(currUserId);
        if(isContainThreeRole){
            List<SysRole> xtgly = allRole.stream().filter(a -> a.getRoleType().equals(SysRole.DEFAULT_XTGLY)).collect(Collectors.toList());
            List<SysRole> aqbmgly = allRole.stream().filter(a -> a.getRoleType().equals(SysRole.DEFAULT_AQBMGLY)).collect(Collectors.toList());
            List<SysRole> aqsjy = allRole.stream().filter(a -> a.getRoleType().equals(SysRole.DEFAULT_AQSJY)).collect(Collectors.toList());
            if(!xtgly.isEmpty()){
                param.put("roleType",SysRole.DEFAULT_XTGLY);
                retRes = resourcesDao.queryResourceByRoleType(param);
            }else if(!aqbmgly.isEmpty()){
                param.put("roleType",SysRole.DEFAULT_AQBMGLY);
                retRes = resourcesDao.queryResourceByRoleType(param);
            }else if(!aqsjy.isEmpty()){
                param.put("roleType",SysRole.DEFAULT_AQSJY);
                retRes = resourcesDao.queryResourceByRoleType(param);
            }
        }else{
            if(threeNumberRes){
                //TODO 通过分配资源与security进行拦截处理URL
                //普通用户不存在三员资源
                Map<String, Object> resAlias = new HashMap<>(6);
                //设置三员权限别名
                resAlias.put("zzglyj",SystemConst.ORG_RES_MAG);
                resAlias.put("resmag",SystemConst.RES_MAG);
                resAlias.put("xtrz",SystemConst.SYSTEM_LOG);
                resAlias.put("syrz",SystemConst.THREENUMBER_LOG);
                resAlias.put("sysProperty",SystemConst.SYSTEM_PROPERTY);
                resAlias.put("sysLogSwitch",SystemConst.SYSTEM_LOG_SWITCH);
                //根据三员权限别名获取到三员权限及所有子权限
                List<String> resToAlias = resourcesDao.queryResByResAlias(resAlias);
                param.put("resIdList",resToAlias.toArray());
                //过滤掉三员权限
                retRes = resourcesDao.queryResNotInThreeNumberBySysAndUserAndRole(param);
            }else{
                //普通用户拥有三员权限
                retRes = resourcesDao.queryResBySysAndUserAndRole(param);
            }
        }
        List<Resources> finalRetRes = retRes;
        retRes.stream().forEach(a ->a.setList(finalRetRes.stream().filter(c -> c.getParentId().equals(a.getResId())).collect(Collectors.toList())));
        return retRes.stream().filter(a -> SystemConst.DEFAULT_TOP_SOURCE_ID.equals(a.getParentId())).collect(Collectors.toList());

    }


    /**
     * 查询租户资源树
     *
     * @param param 查询条件
     * @return ResultData
     */
    public List<Resources> queryResourceByTenantSystem(Map<String, Object> param) {
        /*
        1.超管用户查所有资源
        2.非超管用户 根据用户所属租户查该租户下资源
        2.1 根据当前节点orgId判断当前组织节点是租户还是组织
         若是租户 由此orgId查sys_tenant_resource表中拥有的资源
         若时机构 即isTenant=0 由此orgId先查其所属租户id；再由此租户id查sys_tenant_resource表数据
         */
        String userId = ContextUtil.getCurrentUserId();
        String orgId = (String) param.get("orgId");
        param.put("status", SystemConst.STATUS_Y);
        if (StringUtil.isEmpty(orgId)) {
            /*
             * 查当前用户的租户id 显示该租户下所有资源
             */
            SysOrg userBelongOrg = sysOrgDao.getOrgByUserId(userId);
            param.put("tenantId", sysOrgDao.getTenIdByOrgId(orgId));
            if (SystemConst.SUPER_ADMIN_ID.equals(userId)) {
                param.put("tenantId", SystemConst.TOP_ORG_ID);
            }
        } else {
            param.put("tenantId", sysOrgDao.getTenIdByOrgId(orgId));
        }
        return resourcesDao.queryResByTenantSystem(param);
    }

    /**
     * 查询全部资源URL数据
     *
     * @param classPath controller类路径
     */
    public String getAllMenuPath(String classPath) throws Exception {
        List<ClassInfoModel> list = GetAllMenuPath.GetAllMenuPath(classPath, null, "");
        StringBuilder tips = new StringBuilder();
        for (ClassInfoModel classInfoModel : list) {
            List<MethodInfoModel> methodInfoModelList = classInfoModel.getMethodInfoModelList();
            for (MethodInfoModel methodInfoModel : methodInfoModelList) {
                //完整的URL路径
                String compUrl = methodInfoModel.getCompleteUrl();
                //校验这个url是否已经存在于系统中，如果存在则跳过此方法的后续处理
                List<Resources> resourcesInDB = resourcesDao.queryByUrl(StringPool.PERCENT + compUrl + StringPool.PERCENT);
                if (resourcesInDB != null && resourcesInDB.size() > 0) {
                    continue;
                }
                tips.append(methodInfoModel.getActionDesc() + "<br>");
            }
        }
        return tips.toString();
    }

    /**
     * 查询系统下的公共资源
     *
     * @param map
     */
    public List<Resources> queryPublicResBySystem(Map map) {
        return resourcesDao.queryPublicResBySystem(map);
    }

    /**
     * 验证资源名称是否已存在
     *
     * @param resName 资源名称
     * @return 若存在 返回true 不存在返回false
     */
    public boolean isExistsResName(String resName, String resId) {
        Map<String, String> map = new HashMap<String, String>(2);
        map.put("resName", resName);
        if (StringUtil.isNotEmpty(resId)) {
            map.put("resId", resId);
        }
        int count = resourcesDao.isExistsResName(map);
        return count > 0;
    }

    /**
     * 验证资源别名是否已存在
     *
     * @param alias 资源别名
     * @return 若存在 返回true 不存在返回false
     */
    public boolean isExistsAlias(String alias, String resId) {
        Map<String, String> map = new HashMap<String, String>(2);
        map.put("alias", alias);
        if (StringUtil.isNotEmpty(resId)) {
            map.put("resId", resId);
        }
        int count = resourcesDao.isExistsAlias(map);
        return count > 0;
    }

    /**
     * @param param
     * @return
     */
    public List<Resources> queryResourceData(Map<String, Object> param) {
        List<Resources> list;
        String systemId = (String) param.get("systemId");
        String tenantId = (String) param.get("tenantId");
        if (SystemConst.SUPER_ADMIN_ID.equals(ContextUtil.getCurrentUserId())) {
            /*
            超管查所有
             */
            if (StringUtil.isEmpty(systemId)) {
                systemId = SystemConst.DEFAULT_SYSTEM_ID;
            }
            list = resourcesDao.queryAll(systemId);
            checkOwnerRes(list, tenantId, systemId);
            return list;
        }

        /*

        /*
        非超管
        根据当前用户所属租户 查该租户分配的所有资源；
        只能给该用户所属租户的子租户分配资源
         */

        return null;
    }

    /**
     * 给资源list集合标记某租户已被分配的资源
     *
     * @param list     资源集合list
     * @param tenantId 租户id
     */
    private void checkOwnerRes(List<Resources> list, String tenantId, String systemId) {
        Map<String, Object> map = new HashMap<>(2);
        map.put("tenantId", tenantId);
        map.put("systemId", systemId);
        List<String> queryResourceIdByTenantId = resourcesDao.queryResourceIdByTenantId(map);
        Set<String> tenantOwnerResourceIds = new HashSet(queryResourceIdByTenantId);
        for (Resources res : list) {
            if (tenantOwnerResourceIds.contains(res.getResId())) {
                res.setChecked(Resources.IS_CHECKED_Y);
                res.setIsCheck(true);
            }
        }
    }

    /**
     * 获取对应系统和租户父节点下资源
     *
     * @param systemId 系统id
     * @param tenantId 租户id
     * @param status   状态
     * @param parentId 父节点id
     * @return
     */
    public List<Resources> getBySysTenResStatusParent(String systemId, String tenantId,
                                                      int status, String parentId) {
        Map<String, Object> map = new HashMap<>(4);
        map.put("systemId", systemId);
        map.put("tenantId", tenantId);
        map.put("status", status);
        map.put("parentId", parentId);
        return resourcesDao.getBySysTenResStatusParent(map);
    }

    /**
     * 根据资源ids 查询资源名称
     * @param res list
     * @return  list
     */
    public List<String> queryResNameByResIds(List res){
        return  resourcesDao.queryResNameByResIds(res);
    }

    /**
     * 查询该系统该角色下是否有此功能
     * @param systemId 系统id
     * @param roleId 角色id
     * @param function 功能别名
     * @return  ResourcesUrlExt
     */
    public ResourcesUrlExt getFunctionBySystemIdAndRoleId(String systemId, String roleId, String function) {
        ResourcesUrlExt defaultUrl = resourcesDao.getFunctionBySystemIdAndRoleId(systemId,roleId, function);
        return defaultUrl;
    }
}
